package com.hcm.module.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hcm.kernel.mvc.service.impl.KernelServiceImpl;
import com.hcm.kernel.util.MD5Util;
import com.hcm.kernel.util.MapUtil;
import com.hcm.kernel.util.MyBigDecimal;
import com.hcm.kernel.util.Pagination;
import com.hcm.kernel.wechat.MsgAPI;
import com.hcm.module.admin.dao.IUserDao;
import com.hcm.module.admin.model.User;
import com.hcm.module.admin.service.IUserService;
import com.hcm.module.gzfk.dao.*;
import com.hcm.module.gzfk.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("userService")
public class UserServiceImpl extends KernelServiceImpl<User> implements IUserService {
    @Autowired
    IUserDao userDao;
    @Autowired
    IPayLogDao payLogDao;
    @Autowired
    IPayStreamDao payStreamDao;
    @Autowired
    ITradeDao tradeDao;
    @Autowired
    IGoodsDao goodsDao;
    @Autowired
    ITradeLogDao tradeLogDao;
    @Autowired
    ICashLogDao cashLogDao;

    @Override
    public User login(User user) {
        //校验数据库
        String hql = "from User where account=:account";
        Map<String,Object> map = MapUtil.put("account",user.getAccount());
        List<User> userList = (List<User>) userDao.findByHql(hql,null,map);
        if(userList == null || userList.size()<1){
            user.setOutputFlag(false);
            user.setOutputInfo("帐号错误。");
        }else{
            user.setOutputFlag(false);
            user.setOutputInfo("密码错误");
            for(User user1:userList){
                if(user1.getPwd().equals(MD5Util.encode(user.getPwd()).substring(0,30))){
                    user1.setOutputFlag(true);
                    user = user1;break;
                }
            }
        }
        return user;
    }

    @Transactional(readOnly = false)
    public User update(String json) {
        JSONObject object = JSON.parseObject(json);
        String openId = object.getString("openid");
        User user = new User();
        user.setCode(openId);
        List<User> list = userDao.findByEntity(user,null);
        if(list == null || list.size()<1){
            user.setAccount(openId);
            user.setPwd("");
            user.setCode(openId);
            user.setRegTime(new Timestamp(System.currentTimeMillis()));
            user.setPay(BigDecimal.ZERO);
            user.setLoginNum(2L);
            userDao.insert(user);
        }else{
            User user1 = list.get(0);
            if(object.get("headimgurl")!=null) {
                user.setHeadPic(object.getString("headimgurl"));
                user.setWeChatName(object.getString("nickname"));
            }else {
                //user1.setPay(BigDecimal.ZERO);
                user1.setLoginNum(2L);
            }
            userDao.update(user1);
            user = user1;
        }
        user.setAttr0(object.getString("access_token"));

        return user;
    }

    @Override
    public User pay(String tradeNo, String code) {
        //只有充值记录，才可以进行相关操作
        Map<String,Object> params = new HashMap<>();
        params.put("tradeNo",tradeNo);
        List<?> list = payLogDao.findByHql("from PayLog where status is null and payNo=:tradeNo ", null, params);

        if(list.size()>0){
            PayLog payLog = (PayLog)list.get(0);
            payLog.setStatus("success");
            payLogDao.update(payLog);

            params.put("code",code);//因为是充值，所以这里用户是肯定存在的
            User user = (User)userDao.findByHql("from User where code=:code",null,params).get(0);

            PayStream ps  = new PayStream();
            ps.setOpenId(user.getCode());
            ps.setCreateTime(new Timestamp(System.currentTimeMillis()));
            ps.setBeforePay(user.getPay());

            user.setPay(user.getPay().add(payLog.getPay()));
            ps.setAttr0(tradeNo);//订单号
            ps.setPay(payLog.getPay());
            ps.setAfterPay(user.getPay());
            ps.setType("充值");
            ps.setCode("1");//充值code为1
            payStreamDao.insert(ps);

            userDao.update(user);
            return user;
        }
        return null;
    }

    public User findByCode(String code) {
        Map<String,Object> params = new HashMap<>();
        params.put("code",code);
        List<?> list = userDao.findByHql("from User where code=:code",null,params);
        return (User)list.get(0);
    }

    @Transactional(readOnly = false)
    public User close(String code, String type, String... price) {
        Map<String,Object> params = new HashMap<>();
        params.put("openId",code);
        params.put("type",type);

        List<?> list = tradeDao.findByHql("from Trade where openId=:openId and type=:type ", null, params);
        if(list!=null && list.size()>0) {
            Trade trade = (Trade)list.get(0);

            //得到最新的行情价格
            Goods goods;
            Pagination pagination = new Pagination(1);
            pagination.setPageSize(1);
            if (price == null || price.length == 0) {
                List<?> goodses = goodsDao.findByHql("from Goods g where g.type=:type order by g.createTime desc",pagination ,params);
                goods = (Goods)goodses.get(0);
            } else {
                goods = new Goods();
                goods.setType(type);
                goods.setBuy(new MyBigDecimal(price[1]));
                goods.setSell(new MyBigDecimal(price[1]));
            }

            //写回盈利
            MyBigDecimal p = new MyBigDecimal(trade.getPrice().toString());//买入价
            MyBigDecimal s; //卖出价
            MyBigDecimal yk; //盈利
            if (trade.getXtype().equals("多")) {
                s = new MyBigDecimal(goods.getSell().toString());
                yk = s.subtract(p);
            } else {
                s = new MyBigDecimal(goods.getBuy().toString());
                yk = p.subtract(s);
            }
            if (trade.getType().equals("sliver")) {//如果是白银按0.1千克处理，所以除以10
                yk = yk.divide(new MyBigDecimal(10), 2, MyBigDecimal.ROUND_HALF_UP);
            }

            //如果盈利超出设置的盈利率，那么最大值取保证金*盈利率，而不是最大值
            if (yk.compareTo(trade.getPay().multiply(new MyBigDecimal(trade.getGainPer() / 100))) == 1) {
                yk = new MyBigDecimal(trade.getGainPer() / 100).multiply(trade.getPay());
            }

            //如果亏损超出最大亏损率，则取值为0
            if (yk.compareTo(MyBigDecimal.ZERO.subtract(trade.getPay().multiply(new MyBigDecimal(trade.getLossPer() / 100)))) == -1) {
                yk = MyBigDecimal.ZERO.subtract(trade.getPay());
            }

            User user = findByCode(code);

            //写盈亏到流水
            PayStream ps = new PayStream();
            ps.setOpenId(user.getCode());
            ps.setCreateTime(new Timestamp(System.currentTimeMillis()));
            ps.setBeforePay(user.getPay());
            ps.setPay(yk);
            ps.setOrderNo(trade.getTradeNo());
            user.setPay(user.getPay().add(yk));
            ps.setAfterPay(user.getPay());
            if (yk.compareTo(MyBigDecimal.ZERO) < 1)
                ps.setType("亏损");
            else
                ps.setType("盈利");
            ps.setCode("5");
            payStreamDao.insert(ps);

            //写归还保证金到流水
            PayStream ps1 = new PayStream();
            ps1.setOpenId(user.getCode());
            ps1.setCreateTime(new Timestamp(System.currentTimeMillis()));

            ps1.setBeforePay(user.getPay());
            ps1.setPay(trade.getPay());
            user.setPay(user.getPay().add(trade.getPay()));
            ps1.setAfterPay(user.getPay());
            ps1.setOrderNo(trade.getTradeNo());
            ps1.setType("平仓还保证金");
            ps1.setCode("4");
            payStreamDao.insert(ps1);

            //如果平仓后，金额小于0，则取值0，不可以小于0
            if (user.getPay().compareTo(MyBigDecimal.ZERO) == -1) {
                user.setPay(MyBigDecimal.ZERO);//平仓后金额不可以小于0
            }
            userDao.update(user);

            //将交易记录写入历史表
            TradeLog tradeLog = new TradeLog();
            //tradeLog.setId(trade.getId());
            tradeLog.setPay(trade.getPay());
            tradeLog.setClosePrice(s);//出手价格
            tradeLog.setType(trade.getType());
            tradeLog.setCreateTime(trade.getCreateTime());
            tradeLog.setGainPer(trade.getGainPer());
            tradeLog.setPrice(trade.getPrice());
            tradeLog.setOpenId(trade.getOpenId());
            tradeLog.setYk(yk);
            tradeLog.setXtype(trade.getXtype());
            tradeLog.setLossPer(trade.getLossPer());
            tradeLog.setNickName(user.getWeChatName());
            tradeLog.setTradeNo(trade.getTradeNo());
            if (trade.getType().equals("gold"))
                tradeLog.setName("黄金");
            else if (trade.getType().equals("sliver"))
                tradeLog.setName("白银");
            else if (trade.getType().equals("oil"))
                tradeLog.setName("原油");
            tradeLog.setTime(new Timestamp(System.currentTimeMillis()));//平仓时间


            //发送消息
            if (yk.compareTo(MyBigDecimal.ZERO) == 1) {
                MsgAPI.send(code, "平仓成功：恭喜老板赚钱了，求帮带，求包养.....本单共盈利" + yk + "元！");
            } else {
                MsgAPI.send(code, "平仓成功：本单共亏损" + yk + "元。没关系，顶级投资大师也不是每次都能盈利的，注意控制风险比盈利更重要！损失这点钱算什么，只当买了个冰淇淋掉地上了。");
            }

            tradeLogDao.insert(tradeLog);
            tradeDao.delete(trade);

            //返回盈亏值
            user.setAttr0(yk.toString());
            return user;
        }
        return null;
    }

    @Transactional(readOnly = false)
    public CashLog cash(User user) {
        User user1 = findByCode(user.getCode());
        user1.setPhone(user.getPhone());
        user1.setName(user.getName());

        //记录提现表
        CashLog cash = new CashLog();
        cash.setOpenId(user1.getCode());
        cash.setPay(user1.getPay());
        cash.setPhone(user.getPhone());
        cash.setWeChat(user.getWeChat());
        cash.setCreateTime(new Timestamp(System.currentTimeMillis()));
        cash.setStatus("已申请");
        cash.setFlag("fail");//设置标识默认为fail
        if(user1.getPay().compareTo(MyBigDecimal.ZERO)==0){
            cash.setStatus("申请失败");
            cash.setMessage("您的余额为0，无需提现。");
        }

        //查询充值记录
        Map<String,Object> params = new HashMap<>();
        params.put("openId",user1.getCode());
        try {
            List<?> list = payLogDao.findByHql("from CashLog where openId=:openId ", null,params);
            if(list==null || list.size()<1){
                cash.setStatus("申请失败");
                cash.setAttr0("您尚未有充值记录，未登记您微信钱包信息，很抱歉无法提供提现功能。");
            }else{
                cash.setStatus("success");
            }
        }catch (Exception e){
            cash.setStatus("申请失败");
            cash.setAttr0("您尚未有充值记录，未登记您微信钱包信息，很抱歉无法提供提现功能。");
        }

        //检查持仓状态
        if(cash.getFlag().equals("success")){
            Trade trade = new Trade();
            trade.setOpenId(user.getCode());
            try {
                List<?> list = tradeDao.findByHql("from Trade where  openId=:openId ", null, params);
                if (list != null && list.size() > 0) {
                    cash.setStatus("申请失败");
                    cash.setAttr0("当前您还有持仓中，请确认平仓所有品种后，才能申请提现；");
                }else{
                    cash.setStatus("success");
                }
            }catch(Exception e){

            }

            //检查提现次数
            params.put("result","");
            try {
                List<?> list = cashLogDao.findByHql("from CashLog where  openId=:openId and result=:result ", null,params);
                if (list != null && list.size() > 0) {
                    cash.setStatus("申请失败");
                    cash.setAttr0("您今日已经申请过提现，请到下一个工作日再申请提现。");
                }else{
                    cash.setStatus("success");
                }
            }catch(Exception e){

            }
        }

        if(cash.getStatus().equals("success")){//记录提现流水
            PayStream ps  = new PayStream();
            ps.setOpenId(user.getCode());
            ps.setCreateTime(new Timestamp(System.currentTimeMillis()));
            ps.setBeforePay(user.getPay());

            user1.setPay(new MyBigDecimal(0));

            ps.setPay(MyBigDecimal.ZERO.subtract(cash.getPay()));
            ps.setAfterPay(user1.getPay());
            ps.setType("提现扣减");
            ps.setCode("2");
            payStreamDao.insert(ps);

            cash.setAttr0("申请成功：哎呦，老板！这么快就不玩了，下次带你朋友一起来玩啊。。。恭喜您成功提交提现￥"+user.getPay()+"申请，请关注您的微信钱包，资金将会在工作日24小时内到账。");
            cash.setAttr1("success");
        }

        userDao.update(user1);

        cash.setResult("");
        cashLogDao.insert(cash);
        return cash;
    }
}